package com.wongsi.spring5.controller;

import com.wongsi.spring5.entity.Ingredient;
import com.wongsi.spring5.entity.Ingredient.Type;
import com.wongsi.spring5.entity.Order;
import com.wongsi.spring5.entity.Taco;
import com.wongsi.spring5.repository.IngredientRepository;
import com.wongsi.spring5.repository.TacoRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequestMapping("/design")
/**
 * 添加了@SessionAttributes("order")注解，
 * 并且它有一个新的带有@ModelAttribute注解的方法，即order()方法。
 *
 * order()方法上的@ModelAttribute注解能够确保会在模型中创建一个Order对象。
 * 但是与模型中的Taco对象不同，我们需要订单信息在多个请求中都能出现，
 * 这样的话我们就能创建多个taco并将它们添加到该订单中。
 * 类级别的@SessionAttributes能够指定模型对象（如订单属性）要保存在session中，这样才能跨请求使用。
 */
@SessionAttributes("order")
public class DesignTacoController {

    private final IngredientRepository ingredientRepo;

    private TacoRepository designRepo;

    @Autowired
    public DesignTacoController(
        IngredientRepository ingredientRepo,
        TacoRepository designRepo) {
        this.ingredientRepo = ingredientRepo;
        this.designRepo = designRepo;
    }

    @ModelAttribute(name = "taco")
    public Taco taco() {
        return new Taco();
    }

    @GetMapping
    public String showDesignForm(Model model) {
        List<Ingredient> ingredients = new ArrayList<>();
        ingredientRepo.findAll().forEach(i -> ingredients.add(i));
        Type[] types = Ingredient.Type.values();
        for (Type type : types) {
            model.addAttribute(type.toString().toLowerCase(),
                filterByType(ingredients, type));
        }
        return "design";
    }

    private List<Ingredient> filterByType(List<Ingredient> ingredients, Type type) {
        return ingredients
            .stream()
            .filter(x -> x.getType().equals(type))
            .collect(Collectors.toList());
    }

    @ModelAttribute(name = "order")
    public Order order() {
        return new Order();
    }

    /**
     *
     * @param design
     * @param errors
     * @param order Order参数带有@ModelAttribute注解，
     *              表明它的值应该是来自模型的，
     *              Spring MVC不会尝试将请求参数绑定到它上面。
     * @return
     */
    @PostMapping
    public String processDesign(
        @Valid Taco design, Errors errors,
        @ModelAttribute Order order) {
        if (errors.hasErrors()) {
            return "design";
        }
        Taco saved = designRepo.save(design);
        order.addDesign(saved);
        return "redirect:/orders/current";
    }


}
